package com.liziguo.lzgfp.server.netty.handler;

import com.liziguo.lzgfp.server.record.ForwardRecord;
import com.liziguo.lzgfp.server.util.GlobalUtil;
import com.liziguo.lzgfp.system.codec.AESCodec;
import com.liziguo.lzgfp.system.handler.ForWardHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.TimeUnit;

/**
 * @Author: Liziguo
 * @Date: 2021/12/27 14:38
 */
public class RouterHandler extends SimpleChannelInboundHandler<String> {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    //第几次读到数据
    private int index;

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        //30秒之后如果还没完成路由 则断开连接
        ctx.channel().eventLoop().schedule(() -> {
            if (ctx.pipeline().get(RouterHandler.class) != null) {
                ctx.close();
                logger.debug("断开了一个未能完成路由的连接{}", ctx.channel().remoteAddress());
            }
        }, 30, TimeUnit.SECONDS);
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String s) throws Exception {
        switch (index++) {
            case 0 -> {
                switch (s) {
                    case "lzgfp-cli" -> {
                        //此链接是客户端
                        ctx.pipeline().addLast(new SecurityHandler());
                        ctx.pipeline().remove(this);
                    }
                    case "lzgfp-for" -> {
                        //继续接受数据 此时可以添加TemporaryStorageHandler到末尾 由于读取事件被当前Handler捕获 且没有继续传递下去
                        //因此在当前Handler被移除之前TemporaryStorageHandler不会捕获到读事件
//                        ctx.channel().pipeline().addLast(new TemporaryStorageHandler());
                    }
                    default -> ctx.close();
                }
            }
            case 1 -> {
                ForwardRecord forwardRecord = GlobalUtil.forward.remove(s);
                if (forwardRecord == null) {
                    logger.debug("forKey:{} 不存在", s);
                    ctx.close();
                    return;
                }
                ctx.pipeline().remove(this);
                ctx.pipeline().remove(StringEncoder.class);
                ctx.pipeline().remove(StringDecoder.class);
                //LengthFieldBasedFrameDecoder不能删 因为tcp的粘包机制可能这里一次性读取了三四个包 但目前只处理了两个包 剩下的包还没被处理 如果删除的话会造成丢包的情况
//                ctx.pipeline().remove(LengthFieldPrepender.class);
//                ctx.pipeline().remove(LengthFieldBasedFrameDecoder.class);
                ctx.pipeline().addLast(new AESCodec(forwardRecord.aesKey()));
                //此处可以不添加TemporaryStorageHandler 但是会出现警告
//                ctx.channel().pipeline().addLast(new TemporaryStorageHandler());
                ctx.pipeline().addLast(new ForWardHandler(forwardRecord.channel()));
                forwardRecord.channel().pipeline().addLast(new ForWardHandler(ctx.channel()));
            }
            default -> ctx.close();
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        logger.error(cause.getMessage());
        ctx.close();
    }
}
